(function(win){

	var nameIndex = 0;


	var OldPromise = win.Promise;
	var list, invoke = function(){
		if(list === undefined){
			list = [];
			OldPromise.resolve().then(function(){
				for(var item of list){
					item[0].apply(null,item[1]);
				}
				list = undefined;
			});
		};
		list.push(arguments);
	};

	var Promise = win.Promise = function(fn){
		var promise = this;
		promise.state = "pending";

		promise.name = nameIndex++;
		promise._fn = fn;

		promise._thens = [];

		promise._resolvedThens = [];
		promise._rejectedThens = [];


		try{
			fn(function(result){
				promise._resolve(result);
			}, function(error){
				promise._reject(error);
			})
		}catch(error){
			promise._reject(error);
		}
	};

	Promise.prototype = {
		then:function(resolve, reject){
			if(resolve) this._hasResolve = true; else resolve = function(){};
			if(reject) this._hasReject = true; else reject = function(){};
			var nextPromise = new Promise(function(){});

			var item = [function(result){
				try{
					result = resolve(result);
					nextPromise._resolve(result);
				}catch(error){
					nextPromise._reject(error);
				}
			}, function(error){
				reject(error);
				nextPromise._reject(error);
			}];
			
			switch(this.state){
				case "pending":
					this._thens.push(item);
					break;
				case "fulfilled":

					this._resolvedThens.push(item);

					invoke(item[0],[this.result]);
					break;
				case "rejected":

					this._rejectedThens.push(item);

					invoke(item[1],[this.error]);
					break;
			}

			return nextPromise;
		},
		_resolve:function(result){ var promise = this;
			if(promise.state == "pending"){
				if(result instanceof Promise){
					result.then(function(result2){
						promise.state = "fulfilled";
						promise.result = result2;
						invoke(function(){
							for(var cb of promise._thens){
								if(cb[0]) cb[0](result2);
							}
						});
					});
				} else {
					promise.state = "fulfilled";
					promise.result = result;
					invoke(function(){
						for(var cb of promise._thens){
							if(cb[0]) cb[0](result);
						}
					});
				}
			}
		},
		_reject:function(error){ var promise = this;
			if(promise.state == "pending"){
				promise.state = "rejected";
				promise.error = error;
				invoke(function(){
					if(promise._hasReject){
						for(var cb of promise._thens){
							if(cb[1]) cb[1](error);
						}
					} else {
						throw error;
					}
				});
			}
		}
	}

	Promise.all = function(arr){
		var count = 0, results = [];
		return new Promise(function(resolve, reject){
			if(arr.length == 0){
				resolve();
			} else {
				arr.forEach(function(item, index){
					item.then(function(result){
						results[index] = result;
						count++;
						if(count >= arr.length) resolve(results);
					}, function(error){
						reject(error);
					});
				});
			};
		});
	}

	Promise.resolve = function(result){
		return new Promise(function(resolve, reject){
			return resolve(result);
		});
	}

	Promise.reject = function(error){
		return new Promise(function(resolve, reject){
			return reject(error);
		});
	}


})(window);

